package domain;

import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;

public class Road extends TrafficInfrastructure {
	
	// lengte van een road -1 naar boven afgerond geeft de werkelijke lengte
	//redenen - weg sluit aan op crossroad en deze heeft ook plaats, dus langs elke kant - 0,5, in totaal -1
	//			is de tijd om van het crossroad af te rijden en de weg op, hoort bij crossroad
	// 		  - naar boven over een weg van lengte (4,8 - 1 =) 3,8 ga je 4 tijdseenheden doen (weg zal wat heuvelen)
	//			(dus gewoon naar beneden afronden)
	public Road(CrossRoad start, CrossRoad end, String id) {
		super(id);
		this.start = start;
		this.end = end;
		//bereken segmenten
		Segment begin = start.getSegment();
		Segment stop = end.getSegment();
		makeSegments(begin, stop);
		for(Segment s : getSegments()) {
			s.subscribeCarChangeObserver(new Segment.CarChangeObserver() {
				public void notifyCarChange() {
					notifyObservers();
				}
			});
		}
	}
	
	//verdeeld de road onder in segmenten
	private void makeSegments(Segment begin, Segment stop) {

		//bereken afstand in x en y om weg te blijven van kruispunten  
		float diffX = (float) (Math.cos(getDirection()) * 0.5);
		float diffY = (float) (Math.sin(getDirection()) * 0.5);
		
		float firstX = begin.getX() + diffX;
		float firstY = begin.getY() + diffY;
		float lastX = stop.getX() - diffX;
		float lastY = stop.getY() - diffY;

		//lengte van weg berekenen en naar beneden afronden
		double length = Point2D.distance(firstX, firstY, lastX, lastY);
		int pieces = (int) Math.ceil(length);
		float xpiece = (lastX - firstX)/pieces;	//lengte in x-rich tussen segmenten
		float ypiece = (lastY - firstY)/pieces; //lengte in y-rich tussen segmenten
		
		for(int i = 0; i< pieces; i++){
			segments.add(new Segment(firstX + xpiece/2 + xpiece *i, firstY + ypiece/2 + ypiece*i));
		}
	}
	
	//geeft alle segmenten op road terug, in volgorde van start-crossroad naar end
	public List<Segment> getSegments(){
		return segments;
	}
	
	@Override
	public int getLength(){
		return segments.size();
	}
	
	private List<Segment> segments = new ArrayList<Segment>();
	
	private final CrossRoad start, end;

	//geeft tijd terug om de weg te overbruggen zonder verkeershinder
	public long getTime() {
		return segments.size();
	}
	
	/**
	 * tijdsduur om vanaf gegeven segment op de weg naar het einde van de weg te rijden (zonder verkeershinder)
	 */
	public long getTravelTimeFrom(Segment s) {
		long time = getTime()-1;
		for(Segment roadSeg : getSegments()) {
			if (s == roadSeg) break;
			time--;
		}
		
		return time;
	}
	
	public CrossRoad getStart(){
		return start;
	}
	
	public CrossRoad getEnd(){
		return end;
	}
	
	//geeft hoek van x-as naar weg, tssn -pi/2 en 3/2 Pi met richting weg van start naar end 
	public double getDirection() {
		Segment s = getStart().getSegment();
		Segment e = getEnd().getSegment();
		double angle = Math.atan((e.getY() - s.getY())/(e.getX()-s.getX())); //geeft altijd hoek tssn -90 en +90
		if(e.getX() < s.getX()) //wanneer in 2e of 3e kwadrant moet zijn
			return angle + Math.PI;
		else
			return angle;
	}

	public boolean hasSegment(Segment seg) {
		for(Segment segment : segments){
			if(segment == seg)
				return true;
		}
		return false;
	}
	
}
